package com.hxh.myAop;

import com.hxh.entity.*;
import com.hxh.service.*;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.Objects;

/**
 * @author HXH
 * @description: 记录项目版本变更，记录需要操作的类型，如重启、重新生成表代码、重新初始化项目
 */
@Aspect
@Component
@Slf4j
public class ProjectConfigRecordProjectDetailAspect {

    @Autowired
    private ProjectConfigRecordService projectConfigRecordService;

    @Autowired
    ProjectService projectService;

    @Autowired
    ProjectDetailService projectDetailService;

    /*************************project project_detail表 标志处理 start********************************/

    /**
     * 拦截 updateAll 方法，并获取返回值
     * project表：改变datasource_id、template、addition_component 重新初始化前后端
     * <p>
     * project_detail表：project_name、project_port、project_group、project_dir、base_url 根据类型，初始化x端
     */
    @Around(value = "execution(* com.hxh.service.ProjectService.updateAll(..)) && args(pojo, backendProject, frontendProject)",
            argNames = "joinPoint,pojo,backendProject,frontendProject")
    public Object aroundProjectUpdateAll(
            ProceedingJoinPoint joinPoint,
            Project pojo,
            ProjectDetail backendProject,
            ProjectDetail frontendProject) throws Throwable {

        // 1. 执行前获取旧数据
        Project oldOne = null;

        if (pojo.getId() != null) {
            oldOne = projectService.selectById(pojo.getId());
        }
        ProjectDetail oldBackendProject = null;
        if (backendProject != null && backendProject.getId() != null) {
            oldBackendProject = projectDetailService.selectById(backendProject.getId());
        }
        ProjectDetail oldFrontendProject = null;
        if (frontendProject != null && frontendProject.getId() != null) {
            oldFrontendProject = projectDetailService.selectById(frontendProject.getId());
        }

        // 2. 执行目标方法
        Object result = joinPoint.proceed();

        // 3. 方法执行后处理逻辑
        try {
            boolean success = result instanceof Boolean && (Boolean) result;
            if (success && oldOne != null) {
                boolean hasProjectChange = hasPropertyChanged(oldOne, pojo, "datasourceId", "template", "additionComponent");
                boolean versionChange = false;
                if (hasProjectChange) {
                    projectConfigRecordService.initSystem(oldOne.getId(), "front,back");
                    versionChange = true;
                }
                boolean hasBackendDetailChange = hasPropertyChanged(oldBackendProject, backendProject, "projectName", "projectPort", "projectGroup", "projectDir", "baseUrl");
                boolean hasFrontendDetailChange = hasPropertyChanged(oldFrontendProject, frontendProject, "projectName", "projectPort", "projectGroup", "projectDir", "baseUrl");

                if (hasBackendDetailChange && hasFrontendDetailChange) {
                    projectConfigRecordService.initSystem(oldOne.getId(), "front,back");
                    versionChange = true;
                } else if (hasBackendDetailChange) {
                    projectConfigRecordService.initSystem(oldOne.getId(), "back");
                    versionChange = true;
                } else if (hasFrontendDetailChange) {
                    projectConfigRecordService.initSystem(oldOne.getId(), "front");
                    versionChange = true;
                }
                if (versionChange) {
                    projectConfigRecordService.addLocalVersion(oldOne.getId());
                }
            }
        } catch (Exception e) {
            log.error("项目版本变更记录失败", e);
        }
        return result;
    }


    /**
     * 拦截 insertAll 方法，并获取返回值
     * project表：改变datasource_id、template、addition_component 重新初始化前后端
     */
    @AfterReturning(
            pointcut = "execution(* com.hxh.service.ProjectService.insertAll(..)) && args(pojo, backendProject, frontendProject)",
            returning = "result",
            argNames = "joinPoint,result,pojo,backendProject,frontendProject")
    public void afterProjectInsertAll(
            JoinPoint joinPoint,
            boolean result,
            Project pojo,
            ProjectDetail backendProject,
            ProjectDetail frontendProject
    ) {
        if (result) {
            // 插入成功，触发 initSystem
            projectConfigRecordService.initSystem(pojo.getId(), "front,back");
            projectConfigRecordService.addLocalVersion(pojo.getId());
        }
    }

    /*************************project project_detail表 标志处理 end********************************/

    private static boolean hasPropertyChanged(Object oldObj, Object newObj, String... fieldNames) {
        if (oldObj == null && newObj == null) {
            return false;
        }
        if (oldObj == null || newObj == null) {
            return true;
        }
        for (String fieldName : fieldNames) {
            try {
                Field field = oldObj.getClass().getDeclaredField(fieldName);
                field.setAccessible(true);
                Object oldValue = field.get(oldObj);
                Object newValue = field.get(newObj);
                if (!Objects.equals(oldValue, newValue)) {
                    return true;
                }
            } catch (Exception e) {
                log.warn("无法比较字段: {}", fieldName);
            }
        }
        return false;
    }


}
